package com.himiotech.core.project.web.system;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.himiotech.core.framework.helper.anno.Log;
import com.himiotech.core.framework.helper.constant.UserConstants;
import com.himiotech.core.framework.helper.enums.BusinessType;
import com.himiotech.core.framework.helper.utils.AuthorizationUtils;
import com.himiotech.core.framework.helper.utils.ExcelUtil;
import com.himiotech.core.project.model.entity.role.Role;
import com.himiotech.core.project.model.entity.user.User;
import com.himiotech.core.project.model.entity.user.UserRole;
import com.himiotech.core.project.model.metadata.RoleMetadata;
import com.himiotech.core.project.service.IRoleService;
import com.himiotech.core.project.service.IUserService;
import com.himiotech.core.project.web.base.HimioBaseController;
import com.himiotech.core.project.web.base.model.HimioResult;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 角色信息
 *
 * @author ruoyi
 * @author wuwenbin
 */
@Controller
@RequestMapping("/system/role")
public class RoleController extends HimioBaseController {


    @Autowired
    private IRoleService roleService;
    @Autowired
    private IUserService userService;

    @RequiresPermissions("system:role:view")
    @GetMapping
    public String role() {
        return "system/role/role";
    }

    /**
     * 分配用户
     */
    @RequiresPermissions("system:role:edit")
    @GetMapping("/authUser/{roleId}")
    public String authUser(@PathVariable("roleId") Long roleId, ModelMap mmp) {
        mmp.put("role", roleService.selectRoleById(roleId));
        return "system/role/authUser";
    }

    /**
     * 选择用户
     */
    @GetMapping("/authUser/selectUser/{roleId}")
    public String selectUser(@PathVariable("roleId") Long roleId, ModelMap mmp) {
        mmp.put("role", roleService.selectRoleById(roleId));
        return "system/role/selectUser";
    }

    /**
     * 查询角色信息表列表
     *
     * @param page 分页信息
     * @param role 查询条件
     * @return 表格分页数据
     */
    @RequiresPermissions("system:role:list")
    @PostMapping("/list")
    @ResponseBody
    public HimioResult list(Page<Role> page, Role role) {
        handleOrderBy(request, page);
        page = roleService.selectRoleListPage(page, role);
        return writeJsonLayuiTable(page);
    }

    /**
     * 导出角色信息表列表数据
     *
     * @param role 查询条件
     * @return 导出数据
     */
    @Log(title = "角色信息表", businessType = BusinessType.EXPORT)
    @RequiresPermissions("system:role:export")
    @PostMapping("/export")
    @ResponseBody
    public HimioResult export(Role role) {
        QueryWrapper<Role> query = Wrappers.query();
        if (role != null) {
            query.eq(RoleMetadata.DEL_FLAG.getColName(), 0)
                    .like(StringUtils.isNotEmpty(role.getRoleName()), RoleMetadata.ROLE_NAME.getColName(), role.getRoleName())
                    .like(StringUtils.isNotEmpty(role.getRoleKey()), RoleMetadata.ROLE_KEY.getColName(), role.getRoleKey())
                    .eq(StringUtils.isNotEmpty(role.getStatus()), RoleMetadata.STATUS.getColName(), role.getStatus())
                    .ge(ObjectUtils.isNotEmpty(role.getSearchParams().get("gmtCreateStart")), RoleMetadata.GMT_CREATE.getColName(), role.getSearchParams().get("gmtCreateStart"))
                    .le(ObjectUtils.isNotEmpty(role.getSearchParams().get("gmtCreateEnd")), RoleMetadata.GMT_CREATE.getColName(), role.getSearchParams().get("gmtCreateEnd"));
        }
        List<Role> list = roleService.list(query);
        ExcelUtil<Role> util = new ExcelUtil<>(Role.class);
        return util.exportExcel(list, "角色信息表数据");
    }

    /**
     * 新增角色信息表
     *
     * @param role 新增对象
     * @return 处理结果
     */
    @RequiresPermissions("system:role:add")
    @Log(title = "角色管理 - 新增", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public HimioResult addSave(@Validated Role role) {
        if (UserConstants.ROLE_NAME_NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
            return writeJsonErr("新增角色'" + role.getRoleName() + "'失败，角色名称已存在");
        } else if (UserConstants.ROLE_KEY_NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
            return writeJsonErr("新增角色'" + role.getRoleName() + "'失败，角色权限已存在");
        }
        AuthorizationUtils.clearAllCachedAuthorizationInfo();
        return writeJson(roleService.insertRole(role));
    }


    /**
     * 修改角色信息表
     *
     * @param role 修改对象
     * @return 处理结果
     */
    @RequiresPermissions("system:role:edit")
    @Log(title = "角色管理 -  修改", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public HimioResult editSave(@Validated Role role) {
        roleService.checkRoleAllowed(role);
        if (UserConstants.ROLE_NAME_NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role))) {
            return writeJsonErr("修改角色'" + role.getRoleName() + "'失败，角色名称已存在");
        } else if (UserConstants.ROLE_KEY_NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role))) {
            return writeJsonErr("修改角色'" + role.getRoleName() + "'失败，角色权限已存在");
        }
        AuthorizationUtils.clearAllCachedAuthorizationInfo();
        //包括了role_dept关联关系
        if (roleService.updateRole(role) > 0) {
            setSysUser(userService.getById(getSysUser().getUserId()));
            return writeJsonOk();
        }
        return writeJsonErr();
    }


    @RequiresPermissions("system:role:remove")
    @Log(title = "角色管理 - 删除", businessType = BusinessType.DELETE)
    @PostMapping("/remove")
    @ResponseBody
    public HimioResult remove(String ids) {
        return writeJson(roleService.deleteRoleByIds(ids));
    }

    /**
     * 校验角色名称
     */
    @PostMapping("/checkRoleNameUnique")
    @ResponseBody
    public String checkRoleNameUnique(Role role) {
        return roleService.checkRoleNameUnique(role);
    }

    /**
     * 校验角色权限
     */
    @PostMapping("/checkRoleKeyUnique")
    @ResponseBody
    public String checkRoleKeyUnique(Role role) {
        return roleService.checkRoleKeyUnique(role);
    }

    /**
     * 查询已分配用户角色列表
     */
    @RequiresPermissions("system:role:list")
    @PostMapping("/authUser/allocatedList")
    @ResponseBody
    public HimioResult allocatedList(Page<User> userPage, User user) {
        handleOrderBy(request, userPage);
        userPage = userService.selectAllocatedList(userPage, user);
        return writeJsonLayuiTable(userPage);
    }

    /**
     * 取消授权
     */
    @Log(title = "角色管理 - 取消授权", businessType = BusinessType.GRANT)
    @PostMapping("/authUser/cancel")
    @ResponseBody
    public HimioResult cancelAuthUser(UserRole userRole) {
        return writeJson(roleService.deleteAuthUser(userRole));
    }

    /**
     * 批量取消授权
     */
    @Log(title = "角色管理 - 批量取消授权", businessType = BusinessType.GRANT)
    @PostMapping("/authUser/cancelAll")
    @ResponseBody
    public HimioResult cancelAuthUserAll(Long roleId, String userIds) {
        return writeJson(roleService.deleteAuthUsers(roleId, userIds));
    }


    /**
     * 查询未分配用户角色列表
     */
    @RequiresPermissions("system:role:list")
    @PostMapping("/authUser/unallocatedList")
    @ResponseBody
    public HimioResult unallocatedList(Page<User> userPage, User user) {
        handleOrderBy(request, userPage);
        userPage = userService.selectUnallocatedList(userPage, user);
        return writeJsonLayuiTable(userPage);
    }

    /**
     * 批量选择用户授权
     */
    @Log(title = "角色管理 -  批量选择用户授权", businessType = BusinessType.GRANT)
    @PostMapping("/authUser/selectAll")
    @ResponseBody
    public HimioResult selectAuthUserAll(Long roleId, String userIds) {
        return writeJson(roleService.insertAuthUsers(roleId, userIds));
    }
}